/*
 * Copyright (c) 2011-2014, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.alg.filter.convolve.noborder;

import boofcv.misc.CodeGeneratorBase;

import java.io.FileNotFoundException;

/**
 * @author Peter Abeles
 */
public class GenerateConvolveStandardSparse extends CodeGeneratorBase {
	String className = "ConvolveImageStandardSparse";

	@Override
	public void generate() throws FileNotFoundException {
		setOutputFile(className);
		printPreamble();
		printAllOps("F32", "ImageFloat32","float","",false);
		printAllOps("I32", "ImageUInt8","int"," & 0xFF",false);
		printAllOps("I32", "ImageUInt8","int"," & 0xFF",true);
		printAllOps("I32", "ImageSInt16","int","",false);
		printAllOps("I32", "ImageSInt16","int","",true);
		out.println("}");
	}

	private void printPreamble() {

		out.print("import boofcv.struct.convolve.Kernel1D_F32;\n" +
				"import boofcv.struct.convolve.Kernel1D_I32;\n" +
				"import boofcv.struct.image.ImageFloat32;\n" +
				"import boofcv.struct.image.ImageSInt16;\n" +
				"import boofcv.struct.image.ImageUInt8;\n" +
				"\n" +
				"/**\n" +
				" *\n" +
				" * <p>\n" +
				" * General implementation of {@link boofcv.alg.filter.convolve.ConvolveImageNoBorderSparse}.\n" +
				" * </p>\n" +
				" *\n" +
				" * <p>\n" +
				" * DO NOT MODIFY.  Auto generated by {@link GenerateConvolveStandardSparse}.\n" +
				" * </p>\n" +
				" *\n" +
				" * @author Peter Abeles\n" +
				" */\n" +
				"public class "+className+" {\n\n");
	}

	private void printAllOps(String kernelType, String inputType,
							 String sumType, String bitWise, boolean hasDivide) {
		out.print("\tpublic static "+sumType+" convolve( Kernel1D_"+kernelType+" horizontal, Kernel1D_"+kernelType+" vertical,\n");
		if( hasDivide ) {
			out.print("\t\t\t\t\t\t\t\t"+inputType+" input, int c_x , int c_y, "+sumType+" storage[] ,\n");
			out.print("\t\t\t\t\t\t\t\tint divisorHorizontal ,\n" +
					  "\t\t\t\t\t\t\t\tint divisorVertical )\n");
		} else {
			out.print("\t\t\t\t\t\t\t\t"+inputType+" input, int c_x , int c_y, "+sumType+" storage[] )\n");
		}

		String declareHalf = hasDivide ? "\t\tint halfHorizontal = divisorHorizontal/2;\n" : "";
		String outputHorizontal = hasDivide ? "(total + halfHorizontal)/divisorHorizontal" : "total";
		String outputVertical = hasDivide ? "(total + divisorVertical/2)/divisorVertical" : "total";

		out.print("\t{\n" +
				"\t\tint widthH = horizontal.getWidth();\n" +
				"\t\tint widthV = vertical.getWidth();\n" +
				"\t\tint offsetH = horizontal.getOffset();\n" +
				"\t\tint offsetV = vertical.getOffset();\n" +
				declareHalf +
				"\n" +
				"\t\t// convolve horizontally first\n" +
				"\n" +
				"\t\tfor( int i = 0; i < widthV; i++ ) {\n" +
				"\t\t\tint indexImg = input.startIndex + (i+c_y-offsetV)*input.stride + c_x-offsetH;\n" +
				"\n" +
				"\t\t\t"+sumType+" total = 0;\n" +
				"\t\t\tfor( int j = 0; j < widthH; j++ ,indexImg++) {\n" +
				"\t\t\t\ttotal += (input.data[indexImg]"+bitWise+")*horizontal.data[j];\n" +
				"\t\t\t}\n" +
				"\t\t\tstorage[i] = "+outputHorizontal+";\n" +
				"\t\t}\n" +
				"\n" +
				"\t\t// convolve vertically\n" +
				"\t\t"+sumType+" total = 0;\n" +
				"\t\tfor( int i = 0; i < widthV; i++ ) {\n" +
				"\t\t\ttotal += storage[i]*vertical.data[i];\n" +
				"\t\t}\n" +
				"\t\treturn "+outputVertical+";\n" +
				"\t}\n\n");
	}

	public static void main(String args[]) throws FileNotFoundException {
		GenerateConvolveStandardSparse gen = new GenerateConvolveStandardSparse();
		gen.generate();
	}
}
